package torres.entity;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import torres.fileIO.BasicContainer;
import torres.fileIO.ClassContainer;
import torres.fileIO.PropertyContainer;
import torres.item.ItemManager;
import torres.item.TakeableItem;
import torres.map.World;
import torres.view.ImageLoader;

/**
 * @author Torres
 * NPCs in the game that can sell/buy items to/from player entities.
 * 
 */
public class Merchant extends NPC{
	
	private List<TakeableItem> shopItems;
	private int shopMaxSize;
	
	/**
	 * Creates a Merchant with a given list of items
	 * @param shopItems List of TakeableItems
	 */
	public Merchant(List<TakeableItem> shopItems){
		this.incGold(1000);
		shopMaxSize = 20;
		this.shopItems = new ArrayList<TakeableItem>(shopMaxSize);
		this.shopItems.add(ItemManager.getInstance().getTakeableItem(100));
		this.shopItems.add(ItemManager.getInstance().getTakeableItem(101));
		this.shopItems.add(ItemManager.getInstance().getTakeableItem(102));
		name = "llama";
		displayName = "merchant";
		imageName = name + "E.png";
		loader = new ImageLoader(imageName);
		image = loader.getImage();
	}
	
	/**
	 * Sells item to entity on agreed amount. 
	 * @param item Item to sell
	 * @param entity Entity buying item
	 * @return whether exchange was successful
	 */
	public boolean sellItem(TakeableItem item, Entity entity){
		boolean sold = false;
		int agreedPrice = bargainPrice(item, entity);
		if( entity.buyItem(item, agreedPrice) )
			sold = true;
		
		return sold;
	}
	
	public void interact(Entity e) {
		Avatar a = World.getInstance().getPlayer();
		if(e.equals(a)) {
			a.setInteractedWith(this);
			a.showActionMenu();
		}
	}
	
	/**
	 * Returns agreed price between entity and merchant.
	 * @param item being bargained for
	 * @param entity entity that is bargaining
	 * @return agreed price for buying/selling
	 */
	public int bargainPrice(TakeableItem item, Entity entity) {
		
		if(this.getBargainBonus() == entity.getBargainBonus())
			return item.getItemCost();
		else{
			
			int change = (int)((this.getBargainBonus() - entity.getBargainBonus()) * item.getItemCost());
			change += item.getItemCost();
			return change;
		}
	}
	
	/**
	 * Merchant buying given item from entity
	 * @param item item being sold by entity
	 * @param entity entity selling item
	 */
	public void buyItem(TakeableItem item, Entity entity){
		
		int agreedPrice = (item.getItemCost()/2);
		entity.sellItem(item, agreedPrice);
		if(! isFull())
			shopItems.add(item);
	}
	
	/**
	 * Returns the Merchant's list of items in shop
	 * @return shopList of TakeableItems
	 */
	public Collection<TakeableItem> getShopList(){
		
		return shopItems;
	}
	
	/* (non-Javadoc)
	 * @see torres.entity.NPC#interact()
	 */
	public void interact()
	{
		System.out.println("Welcome to My Shop");
	}
	
	/* (non-Javadoc)
	 * @see torres.entity.NPC#save()
	 */
	public ClassContainer save() {
		ClassContainer curClass = super.save();
		curClass.setName("Merchant");
		if(shopItems!=null) {
			ClassContainer curStruct = new ClassContainer("shopItems");
			for(TakeableItem takeableItem : shopItems)
				curStruct.addProperty(takeableItem.save());
			curClass.addProperty(curStruct);
		}
		return curClass;
	}

	/* (non-Javadoc)
	 * @see torres.entity.NPC#load(torres.fileIO.ClassContainer)
	 */
	public void load(ClassContainer classContainer) {
		super.load(classContainer);
		BasicContainer idCont;
		PropertyContainer property;
		int i=0;
		int id;
		if(shopItems!=null)shopItems.clear();
		if(classContainer.getProperty("shopItems")!=null) {
			ClassContainer shopItemsCont = (ClassContainer)classContainer.getProperty("shopItems");
			while((property = shopItemsCont.getProperty("Item", i))!=null) {
				idCont = (BasicContainer)((ClassContainer)property).getProperty("id");
				id = Integer.parseInt((String)idCont.getValue());
				shopItems.add(ItemManager.getInstance().getTakeableItem(id));
				i++;
			}
		}
	}
	
	/**
	 * Checks to see if Merchant's inventory of TakeableItems is full.
	 * @return True if full, else false.
	 */
	public boolean isFull()
	{
		boolean full = true;
		if( shopItems.size() <= shopMaxSize )
			full = false;
		return full; 
	}
	
	public int BuyPrice(TakeableItem item){
		
		return (item.getItemCost()/2);
	}
	
	public int SellPrice(TakeableItem item, Entity entity)
	{
		return bargainPrice(item, entity);
	}
}
